package com.ccrfid.rmc6.service.personnel;

import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.alarm.AlarmNotifyStrategyEntity;
import com.ccrfid.rmc6.entity.alarm.AlarmRecordEntity;
import com.ccrfid.rmc6.entity.personnel.PersonnelEntity;
import com.ccrfid.rmc6.entity.personnel.PersonnelVitalSignsAlarmConfigEntity;
import com.ccrfid.rmc6.entity.poi.PoiLocationEntity;
import com.ccrfid.rmc6.lbservice3.manager.VitalSignManager;
import com.ccrfid.rmc6.lbservice3.pojo.msg.MsgBloodPressure;
import com.ccrfid.rmc6.lbservice3.pojo.msg.MsgHeartRate;
import com.ccrfid.rmc6.lbservice3.pojo.msg.MsgTemperature;
import com.ccrfid.rmc6.pojo.Constants;
import com.ccrfid.rmc6.repository.alarm.AlarmRecordRepository;
import com.ccrfid.rmc6.repository.personnel.PersonnelRepository;
import com.ccrfid.rmc6.repository.personnel.PersonnelVitalSignsAlarmConfigRepository;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.service.alarm.AlarmNotifyService;
import com.ccrfid.rmc6.service.alarm.AlarmRecordService;
import com.google.common.eventbus.EventBus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.ws.rs.core.Response;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

@Service
public class PersonnelVitalSignAlarmServiceImpl implements PersonnelVitalSignAlarmService {

    private static final Logger logger = LoggerFactory.getLogger(PersonnelVitalSignAlarmServiceImpl.class);

    @Autowired
    private AlarmRecordService alarmRecordService;
    @Autowired
    private AlarmNotifyService alarmNotifyService;
    @Autowired
    private PersonnelService personnelService;
    @Autowired
    private PersonnelVitalSignsAlarmConfigRepository personnelVitalSignsAlarmConfigRepository;
    @Autowired
    private PersonnelRepository personnelRepository;
    @Value("${personnel.vitalsign.alarm.open}")
    private Boolean alarmSwitch;
    @Value("${personnel.vitalsign.alar.linkage.mode}")
    private String alarmLinkageMode;
//    @Value("${personnel.vitalsign.heartrate}")
//    private Integer[] heartRateInterval;
    @Value("${personnel.vitalsign.diastolicpressure}")
    private Integer[] diastolicpressure;
    @Value("${personnel.vitalsign.systolicPressure}")
    private Integer[] systolicPressure;
    @Value("${personnel.vitalsign.temperature}")
    private Double[] temperature;
    @Value("${card.heartRate.max}")
    private Integer maxHeartRate;
    @Value("${card.heartRate.min}")
    private Integer minHeartRate;

    @Override
    public void heartRateAlarm(MsgHeartRate msgHeartRate, PersonnelEntity personnelEntity) {
        if(alarmSwitch){
            PersonnelVitalSignsAlarmConfigEntity personnelVitalSignsAlarmConfigEntity = personnelVitalSignsAlarmConfigRepository.getByPersonnelId(personnelEntity.getId());
            Integer maxHeart = maxHeartRate;
            Integer minHeart = minHeartRate;
            if(null != personnelVitalSignsAlarmConfigEntity) {
                maxHeart = personnelVitalSignsAlarmConfigEntity.getMaxHeartrate();
                minHeart = personnelVitalSignsAlarmConfigEntity.getMinHeartrate();
            }
            if(minHeart > msgHeartRate.getHeartRate()){
                logger.info("判定到低心率异常，异常数据"+ msgHeartRate);
                //todo 如果有心率高的预警，先解除
                closeAlarmRecord(personnelEntity,msgHeartRate.getTime(),Constants.ALARM_TYPE.MAX_HEART_RATE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MIN_HEART_RATE);
                if(null != recordEntity){
                    recordEntity.setAlarmTime(new Timestamp(msgHeartRate.getTime()));
                    logger.info("存入低心率报警记录"+ recordEntity);
                    recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                    //推送告警
                    alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
                }
            }else if(maxHeart < msgHeartRate.getHeartRate()){
                logger.info("判定到高心率异常，异常数据"+ msgHeartRate);
                //todo 如果有心率低得预警，先解除
                closeAlarmRecord(personnelEntity,msgHeartRate.getTime(),Constants.ALARM_TYPE.MIN_HEART_RATE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MAX_HEART_RATE);
                if(null != recordEntity){
                    recordEntity.setAlarmTime(new Timestamp(msgHeartRate.getTime()));
                    logger.info("存入高心率报警记录"+ recordEntity);
                    recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                    //推送告警
                    alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
                }
            }else {
                closeAlarmRecord(personnelEntity,msgHeartRate.getTime(),Constants.ALARM_TYPE.MAX_HEART_RATE);
                closeAlarmRecord(personnelEntity,msgHeartRate.getTime(),Constants.ALARM_TYPE.MIN_HEART_RATE);
            }
        }
    }

    private AlarmRecordEntity setAlarmInfo(PersonnelEntity personnelEntity,Constants.ALARM_TYPE alarmType){
        if(null == alarmRecordService.getAlarmVitalSignRecordUnClosed(personnelEntity.getCardNumber(),alarmType.id)){
            PoiLocationEntity locationEntity = personnelService.getPersonnel3LevelLocation(personnelEntity.getId());
            AlarmRecordEntity recordEntity = new AlarmRecordEntity();
            recordEntity.setPersonnelId(personnelEntity.getId());
            recordEntity.setPersonnelName(personnelEntity.getPersonnelName());
            recordEntity.setPersonnelIds(null);
            recordEntity.setNameAcronym(personnelEntity.getNameAcronym());
            recordEntity.setCardNumber(personnelEntity.getCardNumber());
            recordEntity.setAlarmType(alarmType.id);
            recordEntity.setAlarmTypeName(alarmType.name);
            recordEntity.setAlarmLevel(Constants.ALARM_LEVEL.MINOR.id);
            recordEntity.setAlarmLinkageMode(alarmLinkageMode);
            recordEntity.setClosed(0);
            if(locationEntity != null){
                recordEntity.setLocationId(locationEntity.getId());
                recordEntity.setLocationName(locationEntity.getLocationName());
            }
            recordEntity.setAlarmRuleId(0L);
            return recordEntity;
        }
        return null;
    }

    /**
     * 获取某个类型得预警并恢复
     * @param personnelEntity
     * @param closeTime
     * @param alarmType
     */
    private void closeAlarmRecord(PersonnelEntity personnelEntity, Long closeTime,Constants.ALARM_TYPE alarmType) {
        AlarmRecordEntity recordEntity = alarmRecordService.getAlarmVitalSignRecordUnClosed(personnelEntity.getCardNumber(),alarmType.id);
        if (recordEntity != null) {
            recordEntity.setClosed(1);
            recordEntity.setCloseTime(new Timestamp(closeTime));
            alarmRecordService.updateAlarmRecord(recordEntity);
            //推送恢复信息
            alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
            logger.info("notify AlarmVitalSign, personnelId: {}, alarmRecord: {}", personnelEntity.getId(), recordEntity);
        }

    }

    @Override
    public void bloodPressureAlarm(MsgBloodPressure msgBloodPressure, PersonnelEntity personnelEntity) {
        if(alarmSwitch){
            Integer minDiastolic = diastolicpressure[0];
            Integer maxDiastolic = diastolicpressure[1];
            Integer minSystolic = systolicPressure[0];
            Integer maxSystolic = systolicPressure[1];
            PersonnelVitalSignsAlarmConfigEntity personnelVitalSignsAlarmConfigEntity = personnelVitalSignsAlarmConfigRepository.getByPersonnelId(personnelEntity.getId());
            if(null != personnelVitalSignsAlarmConfigEntity) {
                minDiastolic = personnelVitalSignsAlarmConfigEntity.getMinDiastolicPressure();
                maxDiastolic = personnelVitalSignsAlarmConfigEntity.getMaxDiastolicPressure();
                minSystolic = personnelVitalSignsAlarmConfigEntity.getMinSystolicPressure();
                maxSystolic = personnelVitalSignsAlarmConfigEntity.getMaxSystolicPressure();
            }
            //舒张压判断
            if(minDiastolic > msgBloodPressure.getDiastolicPressure()){
                logger.info("判定到舒张压过低异常，异常数据"+ msgBloodPressure);
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MAX_DIASTOLIC_PRESSURE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MIN_DIASTOLIC_PRESSURE);
                if(null != recordEntity){
                    recordEntity.setAlarmTime(new Timestamp(msgBloodPressure.getTime()));
                    logger.info("存入舒张压过低报警记录"+ recordEntity);
                    recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                    //推送告警
                    alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
                }
            }else if(maxDiastolic < msgBloodPressure.getDiastolicPressure()){
                logger.info("判定到舒张压过高异常，异常数据"+ msgBloodPressure);
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MIN_DIASTOLIC_PRESSURE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MAX_DIASTOLIC_PRESSURE);
                if(null != recordEntity){
                    recordEntity.setAlarmTime(new Timestamp(msgBloodPressure.getTime()));
                    logger.info("存入舒张压过高报警记录"+ recordEntity);
                    recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                    //推送告警
                    alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
                }
            }else {
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MIN_DIASTOLIC_PRESSURE);
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MAX_DIASTOLIC_PRESSURE);
            }
            //收缩压判断
            if(minSystolic > msgBloodPressure.getSystolicPressure()){
                logger.info("判定到收缩压过低异常，异常数据"+ msgBloodPressure);
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MAX_SYSTOLIC_PRESSURE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MIN_SYSTOLIC_PRESSURE);
                if(null != recordEntity){
                    recordEntity.setAlarmTime(new Timestamp(msgBloodPressure.getTime()));
                    logger.info("存入收缩压过低报警记录"+ recordEntity);
                    recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                    //推送告警
                    alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
                }
            }else if(maxSystolic < msgBloodPressure.getSystolicPressure()){
                logger.info("判定到收缩压过高异常，异常数据"+ msgBloodPressure);
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MIN_SYSTOLIC_PRESSURE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MAX_SYSTOLIC_PRESSURE);
               if(null != recordEntity){
                   recordEntity.setAlarmTime(new Timestamp(msgBloodPressure.getTime()));
                   logger.info("存入收缩压过高报警记录"+ recordEntity);
                   recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                   //推送告警
                   alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
               }
            }else {
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MIN_SYSTOLIC_PRESSURE);
                closeAlarmRecord(personnelEntity,msgBloodPressure.getTime(),Constants.ALARM_TYPE.MAX_SYSTOLIC_PRESSURE);
            }
        }
    }


    @Override
    public void temperatureAlarm(MsgTemperature msgTemperature, PersonnelEntity personnelEntity) {
        if(alarmSwitch){
            Double minTemperature = temperature[0];
            Double maxTemperature = temperature[1];
            PersonnelVitalSignsAlarmConfigEntity personnelVitalSignsAlarmConfigEntity = personnelVitalSignsAlarmConfigRepository.getByPersonnelId(personnelEntity.getId());
            if(null != personnelVitalSignsAlarmConfigEntity) {
                minTemperature = personnelVitalSignsAlarmConfigEntity.getMinTemperature();
                maxTemperature = personnelVitalSignsAlarmConfigEntity.getMaxTemperature();
            }
            if(minTemperature > msgTemperature.getTemperature()){
                logger.info("判定到体温压过低异常，异常数据"+ personnelEntity);
                closeAlarmRecord(personnelEntity,msgTemperature.getTime(),Constants.ALARM_TYPE.MAX_TEMPERATURE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MIN_TEMPERATURE);
                if(null != recordEntity){
                    recordEntity.setAlarmTime(new Timestamp(msgTemperature.getTime()));
                    logger.info("存入体温过低报警记录"+ recordEntity);
                    recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                    //推送告警
                    alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
                }
            }else if(maxTemperature < msgTemperature.getTemperature()){
                logger.info("判定到体温压过高异常，异常数据"+ personnelEntity);
                closeAlarmRecord(personnelEntity,msgTemperature.getTime(),Constants.ALARM_TYPE.MIN_TEMPERATURE);
                AlarmRecordEntity recordEntity = setAlarmInfo(personnelEntity,Constants.ALARM_TYPE.MAX_TEMPERATURE);
                if(null != recordEntity){
                    recordEntity.setAlarmTime(new Timestamp(msgTemperature.getTime()));
                    logger.info("存入体温过高报警记录"+ recordEntity);
                    recordEntity = alarmRecordService.createAlarmRecord(recordEntity);
                    //推送告警
                    alarmNotifyService.postAlarmNotify(personnelEntity.getId(), recordEntity);
                }
            }else {
                closeAlarmRecord(personnelEntity,msgTemperature.getTime(),Constants.ALARM_TYPE.MIN_TEMPERATURE);
                closeAlarmRecord(personnelEntity,msgTemperature.getTime(),Constants.ALARM_TYPE.MAX_TEMPERATURE);
            }
        }
    }

    @Override
    public Page<PersonnelVitalSignsAlarmConfigEntity> getPersonnelVitalSignAlarmConfig(SearchCriteria criteria, Pageable pageable) {

        return personnelVitalSignsAlarmConfigRepository.search(criteria, pageable);
    }

    @Override
    public PersonnelVitalSignsAlarmConfigEntity getSinglePersonnelVitalSignAlarmConfig(Long personId) throws AppException {
        if (personId == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.personnel_id_is_null.getCode(),
                    CustomErrors.personnel_id_is_null.getReason(), "");
        }
        PersonnelVitalSignsAlarmConfigEntity entity = personnelVitalSignsAlarmConfigRepository.getByPersonnelId(personId);
        if(entity == null){
            PersonnelEntity personnelEntity = personnelRepository.getById(personId);
            if(personnelEntity != null){
                entity = new PersonnelVitalSignsAlarmConfigEntity();
                entity.setPersonnelId(personnelEntity.getId());
                if(personnelEntity.getPersonnelName() != null){
                    entity.setPersonnelName(personnelEntity.getPersonnelName());
                }
                entity.setMinHeartrate(minHeartRate);
                entity.setMaxHeartrate(maxHeartRate);
                entity.setMinDiastolicPressure(diastolicpressure[0]);
                entity.setMaxDiastolicPressure(diastolicpressure[1]);
                entity.setMinSystolicPressure(systolicPressure[0]);
                entity.setMaxSystolicPressure(systolicPressure[1]);
                entity.setMinTemperature(temperature[0]);
                entity.setMaxTemperature(temperature[1]);
            }else {
                throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                        CustomErrors.person_not_found.getCode(),
                        CustomErrors.person_not_found.getReason(), "");
            }
        }
        return entity;
    }


    @Override
    public PersonnelVitalSignsAlarmConfigEntity addPersonnelVitalSignAlarmConfig(PersonnelVitalSignsAlarmConfigEntity personnelVitalSignsAlarmConfigEntity) throws AppException {
        checkParam(personnelVitalSignsAlarmConfigEntity);
        return personnelVitalSignsAlarmConfigRepository.save(personnelVitalSignsAlarmConfigEntity);
    }

    @Override
    public PersonnelVitalSignsAlarmConfigEntity updatePersonnelVitalSignAlarmConfig(PersonnelVitalSignsAlarmConfigEntity personnelVitalSignsAlarmConfigEntity) throws AppException {
//        if (!personnelVitalSignsAlarmConfigRepository.existsByPersonnelId(personnelVitalSignsAlarmConfigEntity.getPersonnelId())) {
//            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
//                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
//        }
        checkParam(personnelVitalSignsAlarmConfigEntity);
        return personnelVitalSignsAlarmConfigRepository.save(personnelVitalSignsAlarmConfigEntity);
    }

    @Override
    public Boolean deletePersonnelVitalSignAlarmConfig(List<Long> idList) throws AppException {
        if (idList == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.personnel_id_is_null.getCode(), CustomErrors.personnel_id_is_null.getReason(), "");
        }
        for(Long personnelId : idList){
            if (personnelVitalSignsAlarmConfigRepository.existsByPersonnelId(personnelId)) {
                personnelVitalSignsAlarmConfigRepository.deleteByPersonnelId(personnelId);
            }
        }
        return true;
    }

    private void checkParam(PersonnelVitalSignsAlarmConfigEntity entity) throws AppException {
        if (entity.getPersonnelId() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.personnel_id_is_null.getCode(),
                    CustomErrors.personnel_id_is_null.getReason(), "");
        }
        if (entity.getMinHeartrate() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.min_heartrate_is_null.getCode(), CustomErrors.min_heartrate_is_null.getReason(), "");
        }
        if (entity.getMaxHeartrate() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.max_heartrate_is_null.getCode(), CustomErrors.max_heartrate_is_null.getReason(), "");
        }
        if (entity.getMinDiastolicPressure() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.min_diastolic_pressure_is_null.getCode(), CustomErrors.min_diastolic_pressure_is_null.getReason(), "");
        }
        if (entity.getMaxDiastolicPressure() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.max_diastolic_pressure_is_null.getCode(), CustomErrors.max_diastolic_pressure_is_null.getReason(), "");
        }
        if (entity.getMinSystolicPressure() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.min_systolic_pressure_is_null.getCode(), CustomErrors.min_systolic_pressure_is_null.getReason(), "");
        }
        if (entity.getMaxSystolicPressure() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.max_systolic_pressure_is_null.getCode(), CustomErrors.max_systolic_pressure_is_null.getReason(), "");
        }
        if (entity.getMinTemperature() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.min_temperature_is_null.getCode(), CustomErrors.min_temperature_is_null.getReason(), "");
        }
        if (entity.getMaxTemperature() == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.max_temperature_is_null.getCode(), CustomErrors.max_temperature_is_null.getReason(), "");
        }
    }
}
